package com.yfbao.horizon.inspection.engine.impl;

import com.yfbao.horizon.inspection.config.InspectConfig;
import com.yfbao.horizon.inspection.config.ReportTaskConfig;
import com.yfbao.horizon.inspection.dto.ReportDto;
import com.yfbao.horizon.inspection.dto.ReportInfoResult;
import com.yfbao.horizon.inspection.dto.ReportResult;
import com.yfbao.horizon.inspection.entity.SystemInspectRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 巡检指标采集引擎实现类
 * 负责按照配置，定期执行指标巡检，采集对应指标的巡检结果
 */
@Component
public class MetricsCollectorEngine extends AbstractInspectEngine<ReportInfoResult> {

    private static final Logger logger = LoggerFactory.getLogger(MetricsCollectorEngine.class);

    /**
     * 引擎编码
     */
    private static final String ENGINE_CODE = "metrics_collector";

    /**
     * 用于存储周期采集结果的缓存
     */
    private final Map<String, List<SystemInspectRecord>> periodicResultsCache = new ConcurrentHashMap<>();

    /**
     * 定时执行服务
     */
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);

    @Override
    public String getCode() {
        return ENGINE_CODE;
    }

    @Override
    public List<ReportInfoResult> getReportInfo(String taskNo) {
        logger.info("获取指标采集任务 {} 的报告详情", taskNo);
        List<ReportInfoResult> infoList = new ArrayList<>();
        
        // 从缓存中获取该任务的结果并转换为报告详情
        List<SystemInspectRecord> records = periodicResultsCache.get(taskNo);
        if (records != null) {
            for (SystemInspectRecord record : records) {
                ReportInfoResult info = new ReportInfoResult();
                info.setTaskNo(taskNo);
                info.setEnv(record.getInspectEnv());
                info.setInspectCategory(record.getInspectCategory());
                info.setInspectItem(record.getInspectItem());
                info.setCaption("指标采集");
                info.setLabel(record.getInspectItemDesc());
                info.setLevel(convertLevel(record.getInspectItemResult()));
                info.setMessage(record.getInspectItemResult());
                info.setSort(1);
                info.setCollectTime(record.getCollectTime().toString());
                infoList.add(info);
            }
        }
        
        return infoList;
    }

    @Override
    public ReportDto inspectCustomerReportResult(InspectConfig config, ReportTaskConfig reportConfig) {
        logger.info("执行自定义指标采集报告生成，任务编号: {}, 环境: {}", config.getTaskNo(), config.getInspectEnv());
        
        // 实际应用中，这里应该根据自定义逻辑生成报告
        List<ReportInfoResult> infoList = getReportInfo(config.getTaskNo());
        List<String> levels = new ArrayList<>();
        for (ReportInfoResult info : infoList) {
            levels.add(info.getLevel().equals("none") ? "normal" : 
                       info.getLevel().equals("warn") ? "middle" : "high");
        }
        
        String maxLevel = levels.isEmpty() ? "normal" : getMaxLevel(levels);
        ReportResult reportResult = createReportResult(config, reportConfig, maxLevel);
        reportResult.setInspectDesc("自定义指标采集报告");
        
        return createReportDto(reportResult, infoList);
    }

    @Override
    public ReportDto inspectReportResult(InspectConfig config, ReportTaskConfig reportConfig) {
        logger.info("执行规则指标采集报告生成，任务编号: {}, 环境: {}", config.getTaskNo(), config.getInspectEnv());
        
        // 从缓存中获取该配置下的所有周期采集结果
        List<SystemInspectRecord> records = periodicResultsCache.getOrDefault(config.getInspectItem(), new ArrayList<>());
        
        // 转换为报告详情
        List<ReportInfoResult> infoList = new ArrayList<>();
        List<String> levels = new ArrayList<>();
        
        for (SystemInspectRecord record : records) {
            ReportInfoResult info = new ReportInfoResult();
            info.setTaskNo(config.getTaskNo());
            info.setEnv(record.getInspectEnv());
            info.setInspectCategory(record.getInspectCategory());
            info.setInspectItem(record.getInspectItem());
            info.setCaption("指标采集");
            info.setLabel(record.getInspectItemDesc());
            info.setLevel(convertLevel(record.getInspectItemResult()));
            info.setMessage(record.getInspectItemResult());
            info.setSort(1);
            info.setCollectTime(record.getCollectTime().toString());
            
            infoList.add(info);
            levels.add(record.getInspectItemResult());
        }
        
        String maxLevel = levels.isEmpty() ? "normal" : getMaxLevel(levels);
        ReportResult reportResult = createReportResult(config, reportConfig, maxLevel);
        reportResult.setInspectDesc("规则指标采集报告");
        
        return createReportDto(reportResult, infoList);
    }

    @Override
    public SystemInspectRecord inspectCustomerCollect(InspectConfig config) {
        logger.info("执行自定义指标采集，项目: {}, 环境: {}", config.getInspectItem(), config.getInspectEnv());
        return doInspect(config);
    }

    @Override
    public SystemInspectRecord inspectCollect(InspectConfig config) {
        logger.info("执行规则指标采集，项目: {}, 环境: {}", config.getInspectItem(), config.getInspectEnv());
        return doInspect(config);
    }

    @Override
    public void inspectPeriodScan(InspectConfig config) {
        logger.info("执行指标周期扫描，项目: {}, 环境: {}, 周期: {}小时", 
                config.getInspectItem(), config.getInspectEnv(), config.getTriggerCycle());
        
        // 执行周期扫描
        SystemInspectRecord record = doInspect(config);
        
        // 将结果添加到缓存
        String cacheKey = config.getInspectItem();
        periodicResultsCache.computeIfAbsent(cacheKey, k -> new ArrayList<>()).add(record);
        
        // 限制缓存大小
        List<SystemInspectRecord> records = periodicResultsCache.get(cacheKey);
        if (records.size() > 100) {
            records.subList(0, records.size() - 100).clear();
        }
        
        logger.info("周期扫描完成，项目: {}, 结果: {}", config.getInspectItem(), record.getInspectItemResult());
    }

    @Override
    protected SystemInspectRecord doInspect(InspectConfig config) {
        SystemInspectRecord record = new SystemInspectRecord();
        record.setInspectEnv(config.getInspectEnv());
        record.setInspectCategory(config.getInspectCategory());
        record.setInspectItem(config.getInspectItem());
        
        // 模拟指标采集逻辑
        // 实际应用中，这里应该根据配置的promQL从Prometheus获取指标数据
        Map<String, Object> extraParams = config.getExtraParams();
        if (extraParams != null && extraParams.containsKey("testMode")) {
            // 测试模式，返回模拟数据
            String testResult = (String) extraParams.getOrDefault("testResult", "normal");
            record.setInspectItemResult(testResult);
            record.setInspectItemValue(testResult.equals("normal") ? "0" : "1");
            record.setInspectItemDesc("测试模式下的" + (testResult.equals("normal") ? "正常" : "异常") + "结果");
        } else {
            // 正常模式，这里应该调用Prometheus API获取数据
            record.setInspectItemResult("normal");
            record.setInspectItemValue("0");
            record.setInspectItemDesc("指标采集成功");
        }
        
        record.setCollectTime(LocalDateTime.now());
        return record;
    }

    /**
     * 启动周期性任务
     * @param config 巡检配置
     */
    public void startPeriodicTask(InspectConfig config) {
        scheduler.scheduleAtFixedRate(() -> {
            try {
                inspectPeriodScan(config);
            } catch (Exception e) {
                logger.error("周期扫描任务执行失败，项目: {}", config.getInspectItem(), e);
            }
        }, config.getTriggerCycle(), config.getTriggerCycle(), TimeUnit.HOURS);
        
        logger.info("已启动周期性扫描任务，项目: {}, 周期: {}小时", config.getInspectItem(), config.getTriggerCycle());
    }

    /**
     * 关闭调度器
     */
    public void shutdown() {
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
        }
    }
}